﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MonopolyRandy;
using System.Collections.Generic;
using System.Linq;

namespace MonopolyRandyTests
{
    [TestClass]
    public class SpelTests
    {
        private Spel _spel;
        private Bord _monopolyBord;
        private List<Eigendomsbewijs> _eigendomsbewijzen;
        private List<Speler> _spelers;
        private Dictionary<int, bool> worp;

        [TestInitialize]
        public void Setup()
        {
            _spel = new Spel();
            _monopolyBord = new Bord();

            _spelers = new List<Speler>(6)
            {
                new Speler("Herman", 850, _monopolyBord),
                new Speler("Randy", 850, _monopolyBord),
                new Speler("Richard", 850, _monopolyBord),
                new Speler("Guus Geluk", 850, _monopolyBord),
                new Speler("Pech Vogel", 850, _monopolyBord),
                new Speler("Loser", 850, _monopolyBord)
            };

            _eigendomsbewijzen = new List<Eigendomsbewijs>(28)
            {
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[1], 60, 2, 10, 30, 90, 160, 250),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[3], 60, 4, 20, 60, 180, 320, 450),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[6], 100, 6, 30, 90, 270, 400, 550),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[8], 100, 6, 30, 90, 270, 400, 550),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[9], 120, 8, 40, 100, 300, 450, 600),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[11], 140, 10, 50, 150, 450, 625, 750),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[13], 140, 10, 50, 150, 450, 625, 750),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[14], 160, 12, 60, 180, 500, 700, 900),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[16], 180, 140, 70, 200, 550, 750, 950),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[18], 180, 140, 70, 200, 550, 750, 950),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[19], 200, 16, 80, 220, 600, 800, 1000),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[21], 220, 18, 90, 250, 700, 875, 1050),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[23], 220, 18, 90, 250, 700, 875, 1050),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[24], 240, 20, 100, 300, 750, 925, 1100),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[26], 260, 22, 110, 330, 800, 975, 1150),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[27], 260, 22, 110, 330, 800, 975, 1150),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[29], 280, 24, 120, 360, 850, 1025, 1200),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[31], 300, 26, 130, 390, 900, 1100, 1275),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[32], 300, 26, 130, 390, 900, 1100, 1275),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[34], 320, 28, 150, 450, 1000, 1200, 1400),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[37], 350, 35, 175, 500, 1100, 1300, 1500),
                new EigendomsbewijsStraat(null, _monopolyBord.Velden[39], 400, 50, 200, 600, 1400, 1700, 2000),
                new EigendomsbewijsStation(null, _monopolyBord.Velden[5], 200, 25, 50, 100, 200),
                new EigendomsbewijsStation(null, _monopolyBord.Velden[15], 200, 25, 50, 100, 200),
                new EigendomsbewijsStation(null, _monopolyBord.Velden[25], 200, 25, 50, 100, 200),
                new EigendomsbewijsStation(null, _monopolyBord.Velden[35], 200, 25, 50, 100, 200),
                new EigendomsbewijsNuts(null, _monopolyBord.Velden[28], 150, 4, 10),
                new EigendomsbewijsNuts(null, _monopolyBord.Velden[12], 150, 4, 10)
            };

            worp = new Dictionary<int, bool>();
        }

        [TestMethod]
        public void TestOfSpelersCorrectAangemaaktWorden()
        {
            Assert.AreEqual(expected: 6, actual: _spel.GetSpelersList().Count);
        }

        [TestMethod]
        public void TestOfGetSpelersListWerkt()
        {
            var monopolyBord = new Bord();
            var dobbelstenen = _spel.GetDobbelstenen();

            var expectedSpelersList = new List<Speler>()
            {
                new Speler("Herman", 850, monopolyBord),
                new Speler("Randy", 850, monopolyBord),
                new Speler("Richard", 850, monopolyBord),
                new Speler("Guus Geluk", 850, monopolyBord),
                new Speler("Pech Vogel", 850, monopolyBord),
                new Speler("Loser", 850, monopolyBord)
            };

            var actualSpelersList = _spel.GetSpelersList();

            Assert.IsTrue(expectedSpelersList.SequenceEqual(actualSpelersList, new SpelerEqualityComparer()));
        }

        [TestMethod]
        public void TestOfEigendomsbewijsGevondenWordtBijHuidigeVeld()
        {
            Assert.AreEqual(expected: _eigendomsbewijzen[0].GetVeld().GetVeldPositie(), actual: _spel.ZoekVeldEigendomsbewijs(_spel.GetBord().Velden[1]).GetVeld().GetVeldPositie());
        }

        [TestMethod]
        public void ControleerOfSpelerBeslistOmVeldTeKopenKlopt()
        {
            // _speler[0] begint met 850 en eerste eigendomsveld is 60
            Assert.AreEqual(expected: true, actual: _spel.SpelerBeslistOmVeldTeKopen(_spelers[0], _eigendomsbewijzen[0]));
            // _speler[0] heeft 50 en kan dus geen veld van 60 kopen
            _spelers[0].BetaalBedrag(800);
            Assert.AreEqual(expected: false, actual: _spel.SpelerBeslistOmVeldTeKopen(_spelers[0], _eigendomsbewijzen[0]));
        }

        [TestMethod]
        public void ControleerOfBepaalEnBetaalHuurStraatVeldKlopt()
        {
            // één straat van de twee, dus de stad niet compleet
            _spel.BepaalEnBetaalHuurStraatVeld(_eigendomsbewijzen[0], 2, 1, _spel.GetSpelersList()[1], _spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: 848, actual: _spel.GetSpelersList()[1].GetSaldo());

            // twee van de twee straten, dus de stad wel compleet
            _spel.BepaalEnBetaalHuurStraatVeld(_eigendomsbewijzen[0], 2, 2, _spel.GetSpelersList()[2], _spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: 846, actual: _spel.GetSpelersList()[2].GetSaldo());
        }

        [TestMethod]
        public void ControleerOfBepaalEnBetaalHuurStationVeldKlopt()
        {
            // 1 station = 25, 2 = 50, 3 = 100, 4 = 200
            _spel.BepaalEnBetaalHuurStationVeld(_eigendomsbewijzen[22], 1, _spel.GetSpelersList()[1], _spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: 825, actual: _spel.GetSpelersList()[1].GetSaldo());

            _spel.BepaalEnBetaalHuurStationVeld(_eigendomsbewijzen[22], 2, _spel.GetSpelersList()[2], _spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: 800, actual: _spel.GetSpelersList()[2].GetSaldo());

            _spel.BepaalEnBetaalHuurStationVeld(_eigendomsbewijzen[22], 3, _spel.GetSpelersList()[3], _spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: 750, actual: _spel.GetSpelersList()[3].GetSaldo());

            _spel.BepaalEnBetaalHuurStationVeld(_eigendomsbewijzen[22], 4, _spel.GetSpelersList()[4], _spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: 650, actual: _spel.GetSpelersList()[4].GetSaldo());
        }

        [TestMethod]
        public void ControleerOfNutsveldHuurbedragDatBetaaldWordtKlopt()
        {
            // 1 Nuts = 4, 2 = 10
            _spel.BepaalEnBetaalHuurNutsVeld(_eigendomsbewijzen[26], 1, _spel.GetSpelersList()[1], _spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: 846, actual: _spel.GetSpelersList()[1].GetSaldo());

            _spel.BepaalEnBetaalHuurNutsVeld(_eigendomsbewijzen[27], 2, _spel.GetSpelersList()[2], _spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: 840, actual: _spel.GetSpelersList()[2].GetSaldo());
        }

        [TestMethod]
        public void ControleerOfSpelerStraatKopenGoedGaat()
        {
            // Eerste veld kost 60
            _spel.SpelerBeslistEnMaaktAankoopStraat(_spel.GetSpelersList()[0], _eigendomsbewijzen[0]);
            Assert.AreEqual(expected: 790, actual: _spel.GetSpelersList()[0].GetSaldo());
        }

        [TestMethod]
        public void ControleerOfCheckOfStationOpVeldZelfdeIsAlsOpEigendomsbewijsWerkt()
        {
            // Maak speler Herman eigenaar van station zuid (eigendomsbewijs 22)
            _eigendomsbewijzen[22].SetEigenaar(_spel.GetSpelersList()[0]);
            // Op het bord is veld[5] station zuid
            Assert.AreEqual(expected: true, actual: _spel.CheckOfStationOpVeldZelfdeIsAlsOpEigendomsbewijs(_eigendomsbewijzen[22], _monopolyBord.Velden[5], _spel.GetSpelersList()[0]));

        }

        [TestMethod]
        public void ControleerOfCheckOfNutsOpVeldZelfdeIsAlsOpEigendomsbewijsWerkt()
        {
            // Maak speler Herman eigenaar van Waterleiding (eigendomsbewijs 26)
            _eigendomsbewijzen[26].SetEigenaar(_spel.GetSpelersList()[0]);
            // Op het bord is veld[28] Waterleiding
            Assert.AreEqual(expected: true, actual: _spel.CheckOfNutsOpVeldZelfdeIsAlsOpEigendomsbewijs(_eigendomsbewijzen[26], _monopolyBord.Velden[28], _spel.GetSpelersList()[0]));
        }

        [TestMethod]
        public void ControleerOfCheckOfStadOpVeldZelfdeIsAlsOpEigendomsbewijsWerkt()
        {
            // Op het bord is veld[1] Dorpsstraat, Ons Dorp en Herman is zojuist eigenaar gemaakt, dus moet true zijn
            _eigendomsbewijzen[0].SetEigenaar(_spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: true, actual: _spel.CheckOfStadOpVeldZelfdeIsAlsOpEigendomsbewijs(_eigendomsbewijzen[0], _monopolyBord.Velden[1], _spel.GetSpelersList()[0]));

            // Op het bord is veld[3] Brink, Ons Dorp (eigendomsbewijs 1)
            _eigendomsbewijzen[1].SetEigenaar(_spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: true, actual: _spel.CheckOfStadOpVeldZelfdeIsAlsOpEigendomsbewijs(_eigendomsbewijzen[1], _monopolyBord.Velden[3], _spel.GetSpelersList()[0]));
        }

        [TestMethod]
        public void ControleerOfTelAantalStratenVanHuidigeStadKlopt()
        {
            // Ons Dorp heeft 2 straten (veld 1 en 3), Arnhem heeft 3 straten (veld 6, 8 en 9)
            Assert.AreEqual(expected: 2, actual: _spel.TelAantalStratenVanHuidigeStad(_monopolyBord.Velden[1]));
            Assert.AreEqual(expected: 3, actual: _spel.TelAantalStratenVanHuidigeStad(_monopolyBord.Velden[6]));
            Assert.AreEqual(expected: 3, actual: _spel.TelAantalStratenVanHuidigeStad(_monopolyBord.Velden[9]));

        }

        [TestMethod]
        public void ControleerOfBetaalHuurAanEigenaarKlopt()
        {
            // Randy gaat huur betalen. Herman is eigenaar van Dorpsstraat, Ons Dorp en niet van Brink, Ons Dorp -> kosten voor onbebouwde huur is 2
            _spel.GetSpelersList()[0].KoopEigendomsbewijs(_spel.GetEigendomsbewijsList()[0]);
            _spel.BetaalHuurAanEigenaar(_spel.GetSpelersList()[0], _monopolyBord.Velden[1], _eigendomsbewijzen[0], _spel.GetSpelersList()[1]);
            Assert.AreEqual(expected: 848, actual: _spel.GetSpelersList()[1].GetSaldo());

            // Randy gaat huur betalen. Herman is eigenaar beide straten in de stad Ons Dorp -> kosten voor onbebouwde huur is 8 (848 - 8 = 840)
            _spel.GetSpelersList()[0].KoopEigendomsbewijs(_spel.GetEigendomsbewijsList()[1]);
            _spel.BetaalHuurAanEigenaar(_spel.GetSpelersList()[0], _monopolyBord.Velden[3], _eigendomsbewijzen[1], _spel.GetSpelersList()[1]);
            Assert.AreEqual(expected: 840, actual: _spel.GetSpelersList()[1].GetSaldo());

            // Randy gaat huur betalen. Herman is eigenaar van Station Zuid en Oost -> kosten voor huur is 50 (840 - 50 = 790)
            _spel.GetSpelersList()[0].KoopEigendomsbewijs(_spel.GetEigendomsbewijsList()[22]);
            _spel.GetSpelersList()[0].KoopEigendomsbewijs(_spel.GetEigendomsbewijsList()[25]);
            _spel.BetaalHuurAanEigenaar(_spel.GetSpelersList()[0], _monopolyBord.Velden[5], _spel.GetEigendomsbewijsList()[22], _spel.GetSpelersList()[1]);
            Assert.AreEqual(expected: 790, actual: _spel.GetSpelersList()[1].GetSaldo());

            // Randy gaat huur betalen. Herman is eigenaar van beide Nutsbedrijven -> kosten voor huur is 10 (790 - 10 = 780)
            _spel.GetSpelersList()[0].KoopEigendomsbewijs(_spel.GetEigendomsbewijsList()[26]);
            _spel.GetSpelersList()[0].KoopEigendomsbewijs(_spel.GetEigendomsbewijsList()[27]);
            _spel.BetaalHuurAanEigenaar(_spel.GetSpelersList()[0], _monopolyBord.Velden[28], _spel.GetEigendomsbewijsList()[27], _spel.GetSpelersList()[1]);
            Assert.AreEqual(expected: 780, actual: _spel.GetSpelersList()[1].GetSaldo());
        }

        [TestMethod]
        public void ControleerOfSpelerOnderneemtActieIndienVeldKoopbaarIsWerkt()
        {
            // Op het bord is veld[1] Dorpsstraat, Ons Dorp en Herman gaat dit veld willen kopen
            _spel.SpelerOnderneemtActieIndienVeldKoopbaarIs(_spel.GetBord().Velden[1], _spel.GetSpelersList()[0]);
            // Controleren of Herman daadwerkelijk de eigenaar is geworden van Dorpsstraat, Ons Dorp
            Assert.AreEqual(expected: _spel.GetSpelersList()[0], actual: _spel.GetEigendomsbewijsList()[0].GetEigenaar());

            // Herman is inmiddels eigenaar van Dorpsstraat, Ons Dorp en Randy belandt op dit veld.
            // Randy kan dit veld niet kopen, maar zal huur moeten gaan betalen.
            _spel.SpelerOnderneemtActieIndienVeldKoopbaarIs(_spel.GetBord().Velden[1], _spel.GetSpelersList()[1]);
            // Randy moet 2 euro aan Herman betalen
            Assert.AreEqual(expected: 848, actual: _spel.GetSpelersList()[1].GetSaldo());
            // Herman heeft eerst 60 euro moeten betalen en heeft 2 euro van Randy ontvangen
            Assert.AreEqual(expected: 792, actual: _spel.GetSpelersList()[0].GetSaldo());
        }

        [TestMethod]
        public void ControleerOfBetaalBelastingWerkt()
        {
            // Herman moet op veld 4 een boete betalen van 200 euro
            _spel.BetaalBelastingIndienNodig(_spel.GetBord().Velden[4], _spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: 650, actual: _spel.GetSpelersList()[0].GetSaldo());

            // Randy moet op veld 38 een boete betalen van 100 euro
            _spel.BetaalBelastingIndienNodig(_spel.GetBord().Velden[38], _spel.GetSpelersList()[1]);
            Assert.AreEqual(expected: 750, actual: _spel.GetSpelersList()[1].GetSaldo());
        }

        [TestMethod]
        public void ControleerOfSpelerPionLatenVerzettenWerkt()
        {
            worp.Add(7, false);

            // Herman gaat vanaf start 7 plaatsen vooruit
            _spel.SpelerPionLatenVerzetten(worp, _spel.GetSpelersList()[0]);
            Assert.AreEqual(expected: _spel.GetBord().Velden[7], actual: _spel.GetSpelersList()[0].GetPionVeld());

            // Randy komt met dobbelen over start en ontvangt salaris
            worp.Add(4, false);
            // Eerst even Randy op veld 38 zetten
            _spel.GetSpelersList()[1].VerzetPion(38);
            _spel.SpelerPionLatenVerzetten(worp, _spel.GetSpelersList()[1]);
            Assert.AreEqual(expected: _spel.GetBord().Velden[2], actual: _spel.GetSpelersList()[1].GetPionVeld());
            Assert.AreEqual(expected: 1050, actual: _spel.GetSpelersList()[1].GetSaldo());
        }

        [TestMethod]
        public void ControleerOfSpelerUitGevangenisLatenOntsnappenWerkt()
        {
            // Eerst Herman in de gevangenis zetten.
            _spel.GetSpelersList()[0].GaDirectNaarDeGevangenis(_monopolyBord.Velden[10]);
            // Controleer of Herman daadwerkelijk in de gevangenis zit.
            Assert.AreEqual(expected: true, actual: _spel.GetSpelersList()[0].GetPion().ZitVast);

            // Dan Herman weer uit de gevangenis laten ontsnappen
            worp.Add(7, false);
            _spel.SpelerUitGevangenisLatenOntsnappen(_spel.GetSpelersList()[0], worp);
            Assert.AreEqual(expected: false, actual: _spel.GetSpelersList()[0].GetPion().ZitVast);
        }

        [TestMethod]
        public void TestOfSaldoVanSpelersVeranderdIsNa50Beurten()
        {
            _spel.SpeelAantalBeurten(100);

            Assert.AreNotEqual(850, actual: _spel.GetSpelersList()[0].GetSaldo());
            Assert.AreNotEqual(850, actual: _spel.GetSpelersList()[1].GetSaldo());
        }
    }
}
